package com.markerhub.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.markerhub.common.RedisKey;
import com.markerhub.common.lang.Result;
import com.markerhub.entity.User;
import com.markerhub.handler.UserThreadLocal;
import com.markerhub.mapper.UserMapper;
import com.markerhub.pojo.dto.UserDto;
import com.markerhub.repository.Wx_UserRepository;
import com.markerhub.service.UserService;
import com.markerhub.service.WxService;
import com.markerhub.util.JWTUtils;
import com.markerhub.vo.WXAuth;
import com.markerhub.vo.WxUserInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 服务实现类
 *
 * @author MaXiaofeng
 * @since 2022-1-28
 */

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private Environment env;
    @Autowired
    private WxService wxService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private UserMapper userMapper;
    @Resource
    private Wx_UserRepository wx_userRepository;


    @Override
    public boolean login(String username, String password) {
        return false;
    }

    /**
     * 微信小程序登录第一步
     * 1.首先拼接一个url 微信登陆凭证校验接口
     * 2.发起http调用，获取微信的返回结果
     * 3.存到redis中
     * 4. 生成sessionId，返回给前端，作为当前需要登陆用户的标识
     * 5.生成一个sessionId，用户在点击微信登陆的时候我们可以标识 用户是谁
     *
     * @param code
     * @return
     */

    @Override
    public Result getSessionId(String code) {
        JSONObject jsonObject = JSON.parseObject(code);
        String Code = (String) jsonObject.get("code");
        String appid = env.getProperty("wxmini.appid");
        String appSecret = env.getProperty("wxmini.secret");
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
        String replaceUrl = url.replace("{0}", appid).replace("{1}", appSecret).replace("{2}", Code);
        //发起http调用，获取微信的返回结果
        String res = HttpUtil.get(replaceUrl);
        ///随机生成一个标识
        String uuid = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(RedisKey.WX_SESSION_ID + uuid, res, 30, TimeUnit.MINUTES);
        Map<String, String> map = new HashMap<>();
        map.put("sessionId", uuid);
        return Result.success(map);
    }

    /**
     * 1、通过WXAuth中的值进行解密
     * 2、解密完成之后，获取用户信息 其中包含openID、性别、名称、头像
     * 3、openId唯一，需要去user表中查询openId是否存在，如果存在则已该用户的身份登录成功
     * 4、不存在则是新用户，注册流程登陆成功
     * 5、使用jwt技术，生成一个token，提供给前端token令牌，用户在下次访问的时候，携带token来访问
     * 6、后端通过对token的验证，知道此用户是否处于登陆状态，是哪个用户登陆的
     *
     * @param wxAuth
     * @return
     */
    @Override
    public Result authLogin(WXAuth wxAuth) {
        try {
            String userInfoJson = wxService.wxDecrypt(wxAuth.getEncryptedData(), wxAuth.getSessionId(), wxAuth.getIv());
            WxUserInfo wxUserInfo = JSON.parseObject(userInfoJson, WxUserInfo.class);
            String openId = WxService.getOpenId();
            wxUserInfo.setOpenId(openId);
            User user = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getOpenid, openId).last("limit 1"));
            UserDto userDto = new UserDto();
            if (user == null) {
                userDto.from((wxUserInfo));
                userDto.setCtime(new Timestamp(System.currentTimeMillis()));//当前时间  YYYY-MM-DD HH:MM:SS.[fff...]
                //注册
                return this.wx_register(userDto);
            } else {
                //登录
                userDto.setId(user.getId());
                return this.wx_login(userDto);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.fail("");
    }

    /**
     * 微信登陆 使用jwt技术，生成一个token，提供给前端token令牌，用户在下次访问的时候，携带token来访问
     *
     * @param userDto
     * @return
     */
    public Result wx_login(UserDto userDto) {
        String token = JWTUtils.sign(userDto.getId());
        userDto.setToken(token);
        //openId、unionId不予前端展示
        userDto.setOpenid(null);
        userDto.setWx_union_id(null);
        //需要把token存入redis，讲value存为userDto
        //下次用户访问需要登陆资源的时候，可以根据token拿到用户的详细信息
        redisTemplate.opsForValue().set(RedisKey.TOKEN + token, JSON.toJSONString(userDto), 7, TimeUnit.DAYS);
        return Result.success(userDto);
    }

    /**
     * 微信用户注册，将新用户信息放入数据库中
     *
     * @param userDto
     * @return
     */
    public Result wx_register(UserDto userDto) {
        User user = new User();
        BeanUtils.copyProperties(userDto, user);
        wx_userRepository.save(user);
        userDto.setId(user.getId());
        return this.wx_login(userDto);
    }

    /**
     * 1、根据token来验证此token是否有效
     * 2、refresh 如果为true代表刷新 重新生成 token和 redis里面重新存储 续期
     * 3、refresh 如果为false直接返回用户信息 redis中查询出来直接返回
     *
     * @param refresh
     * @return
     */
    @Override
    public Result userInfo(Boolean refresh) {
        UserDto userDto = UserThreadLocal.get();
        //refresh 如果为true代表刷新 重新生成 token和 redis里面重新存储 续期
        if (refresh) {
            String token = JWTUtils.sign(userDto.getId());
            userDto.setToken(token);
            redisTemplate.opsForValue().set(RedisKey.TOKEN + token, JSON.toJSONString(userDto), 7, TimeUnit.DAYS);
        }

        return Result.success(userDto);
    }

    /**
     * 绑定用户手机号
     *
     * @param userId
     * @param phone
     * @return
     */
    @Override
    public Result bindUserPhone(int userId, String phone) {
        if (userMapper.updateUserByPhone(userId, phone) >= 0) {
            return Result.success("用户绑定手机号成功");
        }
        return Result.fail("用户绑定手机号失败");
    }
}
